#include<iostream>
#include<memory>
#include<functional>
using namespace std;

struct Date
{
	int _year;
	int _month;
	int _day;

	Date(int year = 1, int month = 1, int day = 1)
		:_year(year)
		, _month(month)
		, _day(day)
	{}

	~Date()
	{
		cout << "~Date()" << endl;
	}
};

namespace self
{
	template<class T>
	class shared_ptr
	{
	public:
		shared_ptr(T* ptr = nullptr)
			:_ptr(ptr)
			,_count(new int(1))
		{}

		template<class D>
		shared_ptr(T* ptr, D del)
			: _ptr(ptr)
			, _count(new int(1))
			, _del(del)
		{}

		shared_ptr(const shared_ptr<T>& p)
			:_ptr(p._ptr)
			,_count(p._count)
		{
			(*_count)++;
		}

		//sq1 = sq3
		//sq1 = sq2
		//sq1 = sq1
		shared_ptr<T>& operator=(const shared_ptr<T>& p)
		{
			if (_ptr != p._ptr)
			{
				if (--(*_count) == 0)
				{
					delete _ptr;
					delete _count;
				}

				_ptr = p._ptr;
				_count = p._count;
				(*_count)++;
			}

			return *this;
		}

		~shared_ptr()
		{
			if (--(*_count) == 0)
			{
				_del(_ptr);
				delete _count;
			}
		}

		T* operator->()
		{
			return _ptr;
		}

		T& operator*()
		{
			//*count++
			return *_ptr;
		}

	private:
		T* _ptr;
		int* _count;

		function<void(T* ptr)> _del = [](T* ptr) {delete ptr; };
	};
}

int main()
{
	/*self::shared_ptr<Date> sq1(new Date);
	self::shared_ptr<Date> sq2(sq1);
	self::shared_ptr<Date> sq3 = sq2;
	self::shared_ptr<Date> sq4;
	sq4 = sq1;
	self::shared_ptr<Date> sq5(new Date);*/

	self::shared_ptr<Date> sq1(new Date[10], [](Date* ptr) {delete[] ptr; });
	self::shared_ptr<Date> sq2 = sq1;
	self::shared_ptr<Date> sq3;
	sq3 = sq1;


	//self::shared_ptr<Date> sq2(new Date[10]);
	//shared_ptr<int> sq2(new int[10], [](int* i) {delete[] i; });



	return 0;
}